Migrate content layer to VaultCMS/Obsidian conventions#13
Merged
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-accept schema Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- git mv 19 images + 2 videos into src/content/posts/<slug>/ - wrote index.md with new frontmatter shape (date, tags as strings, image: featured.png) - converted all <Figure>/<Video> to remark syntax; link-caption figure uses markdown image + emphasis (auto-linked URL in caption) - expanded images.ts glob to cover co-located src/content/posts/** - added resolveFeatureImagePath() to utils/images.ts; updated [slug].astro, rss.xml.ts, posts.json.ts, post-markdown.ts to prefix slug for bare-basename image paths - videos served via public/<slug>/ (pipeline concern: remark video-embeds emits relative basenames, Astro doesn't auto-copy co-located mp4s to dist) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ved from public/) Videos espresense-tracking-demo.mp4 and litter-box-sensor-demo.mp4 were duplicated in src/content/posts/whose-turn-.../. Per convention, videos live only in public/<slug>/, not in content. Post embeds are basename-only, so they resolve to the served copies. Verified: build passes, both videos render with video-card class in dist output. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…d vars Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fold resolveImage/isGif globs from components/mdx/images.ts into
src/utils/images.ts (kept legacy src/assets/content/images/** glob
for site/ assets: icon, logo, avatar, og-default)
- Simplify post-markdown.ts: delete JSX-component rewriter (Figure/
Video/Tweet/Instagram); posts are native .md, body served as-is
- Delete src/components/mdx/{Figure,Video,Tweet,Instagram}.astro,
images.ts, media.ts
- Remove empty dirs: src/assets/content/images/posts, src/assets/content/media
- Build: 130 pages, 0 check errors, 0 broken links
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Generate Cloudflare _redirects entries for Ghost -2 dedup slugs that
changed during the VaultCMS migration. Adds scripts/gen-tag-redirects.mjs
to extract legacy {slug, name} pairs from git history (rev 002941f) and
emit redirect lines where oldSlug !== slugify(name).
Result: 2 redirects added (/tag/3d-printing-2/ and /tag/home-assistant-2/).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Change "nor a image" to "nor an image" in OG fallback comment - Mark MDX as "(compat)" in astro.config.mjs documentation Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
posts | 37d615c | Commit Preview URL Branch Preview URL |
Jun 22 2026, 02:40 PM |
Adds the VaultCMS vault (.obsidian config + bundled CMS plugins, _bases/Home.base, _GUIDE.md) under src/content so the posts collection is editable in Obsidian. Per-user workspace state (workspace.json/workspace-mobile.json) is gitignored via **/ patterns that match the vault's actual src/content location. The vault config lives outside src/content/posts/**, so the content glob does not pick it up; build stays at 130 pages with no stray routes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
VaultCMS setup wizard configured the Obsidian plugins for this vault: folder-based posts, link base path "/" (posts live at root), the title/date/description/tags/image/draft property mappings, and the new-post template. Updates plugin data.json files + _bases/Home.base. Site build unaffected (130 pages, content glob excludes the vault). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ort) Migration is complete, so drop what was only needed to get there: - delete scripts/migrate-to-vaultcms.mjs and scripts/gen-tag-redirects.mjs (one-time codemod + redirect generator; their output is committed) - remove the now-unused @astrojs/mdx integration + import, narrow the posts glob to **/*.md, and drop @astrojs/mdx from dependencies (no .mdx remain; remark plugins use @astrojs/markdown-remark, not mdx) Build verified: astro check 0 errors/0 hints, 130 pages, links clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Removes the source-tree split: video files and their posters move from public/<slug>/ back into the post folder (src/content/posts/<slug>/), co-located with the post's images and index.md — one source of truth per post. A new astro:build:done integration (copy-post-media) parses each post's ![[...]] embeds and copies the referenced video + poster files into dist/<slug>/, so they're still served at /<slug>/<file>. The split now exists only in dist (build output), not in the repo. Runs before strip-image-metadata so copied posters are EXIF-scrubbed. Build verified: check 0 errors, 21 media files copied, 130 pages, links clean. Docs (AGENTS.md, building-and-content.md) updated to the co-located convention. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A project-scoped skill (.claude/skills/creating-blog-posts) documenting the mechanics of adding a post to this repo: folder-per-post index.md layout, the frontmatter schema, co-located image/caption/video conventions, string tags, build verification, and the real footguns (empty date strings, raw-HTML images, draft not hiding posts). Defers prose/voice to the oz-skills:blog-post-writer skill; covers everything needed to get a draft into the repo correctly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… blog Swaps the bundled Oxygen theme for a custom "0xZ" theme so editing posts in Obsidian looks like the live site. Palette + fonts are taken verbatim from src/styles/global.css: gold accent (#997700 light / #ffd102 dark) on a near-white / near-black surface, Mulish for text + extra-bold headings, IBM Plex Mono for code. Defines .theme-light / .theme-dark blocks so the editor follows the OS scheme like the blog does. appearance.json now points at 0xZ. Theme lives in the vault (src/content/.obsidian), outside the posts glob, so the site build is unaffected (130 pages, 0 errors). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
VaultCMS's onboarding guide is no longer needed now that the setup wizard has been run and the vault is configured. It lives outside the posts glob, so the build is unaffected (130 pages, 0 errors). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- README "At a glance": Content is now folder-based Markdown collections
(editable in Obsidian via VaultCMS), images co-located; add a pointer to the
creating-blog-posts skill.
- design-system.md: replace the "MDX component kit" section with the Markdown +
remark-plugin model (remark-image-captions / remark-video-embeds), keeping the
still-accurate rendered CSS-class docs; fix <Figure wide> -> {wide}.
- building-and-content.md: drop the stale "MDX (compat)" note (@astrojs/mdx removed).
- AGENTS.md: point "Adding content" at the creating-blog-posts skill; document the
in-repo VaultCMS vault location and the 0xZ Obsidian theme.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The VaultCMS install committed the full third-party plugin bundles (.obsidian/plugins/*/main.js + styles.css) — ~5.6 MB of code we don't maintain. Gitignore the plugin code and untrack it, keeping only the small per-plugin config (manifest.json + data.json, ~80 KB) so the vault stays documented and re-installable via `npx create-vaultcms`. Files remain on disk, so local Obsidian is unaffected. Tracked plugin footprint: 5,691,368 -> 81,309 bytes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Since plugin code is no longer vendored, a fresh clone has the vault config but not the plugin bundles. Document the one-time `npx create-vaultcms` restore step (Obsidian-editing only; not needed to build/preview/deploy) in README, AGENTS.md, and building-and-content.md. Also fixes the stale "config installed separately" wording in building-and-content's Obsidian section. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Makes the blog editable in Obsidian via VaultCMS by adopting VaultCMS/Obsidian content conventions — while keeping the existing Astro 6 theme, URLs, Cloudflare deploy, and visual output the same. We did not adopt the astro-modular theme/stack.
What changed
src/content/posts/<slug>/index.md(plain Markdown, folder name = slug = unchanged URL). No more.mdx+ JSX component kit.), still optimized to hashed/_astro/(WebP + srcset; GIFs preserved).*emphasis*line immediately under an image →<figcaption>(may contain a[text](url)link).{wide}marker for the wide column. Implemented bysrc/plugins/remark-image-captions.mjs, replicating the old<Figure>output.![[clip.mp4|poster=…|title=…]]; video + poster files live inpublic/<slug>/. Implemented bysrc/plugins/remark-video-embeds.mjs, replicating<Video>.date/description/image/imageAlt/imageCaption/tags: string[]/draft+ SEO overrides (waspubDate/excerpt/featureImage/{slug,name}tags). Tag URL slug =slugify(name).src/utils/images.ts. Markdown-for-agents (Accept: text/markdown,/<slug>.md) simplified to serve the native body.markdown.processor: unified({...}); Shiki nord preserved.AGENTS.md,CLAUDE.md,docs/building-and-content.md).Output preservation
llms.txt, dark mode all intact.-2duplicate slugs (home-assistant-2,3d-printing-2) merged into their canonical tags — both 301-redirected inpublic/_redirects.public/<slug>/.Verification
npm run check: 0 errors ·npm run build: 130 pages ·npm run check:links: 0 broken (2822 refs). Remark plugins covered bynode --test.npm run lhciruns in CI.Not included (follow-ups)
.obsidian/+_bases/) — to be installed separately; the repo is already structurally VaultCMS-compatible.🤖 Generated with Claude Code